<?php

namespace App\Jobs;

use App\Models\Payment\PaymentChannel;
use App\Models\Payment\Platform\ChinaUms;
use App\Models\Payment\Platform\EbankPay;
use App\Models\Payment\Platform\FuiouAggregatePay;
use App\Models\Payment\Platform\FuiouPay;
use App\Models\Payment\Platform\UnionPay;
use App\Models\Payment\RefundOrder;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Psr\Log\LoggerInterface;

class OrderRefund implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $refundOrder;

    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct(RefundOrder $refundOrder)
    {
        $this->refundOrder = $refundOrder;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        $refundOrder = $this->refundOrder;

        $refundSuccess = false;
        $err = '';
        try {
            if ($refundOrder->refund_status !== RefundOrder::STATUS_PENDING) {
                throw new \Exception('退款单不为待处理状态');
            }

            if ($refundOrder->refund_type !== RefundOrder::REFUND_TYPE_ORIGINAL_RETURN) {
                throw new \Exception('未开通的退款方式');
            }

            $hadRefundedOrders = RefundOrder::query()->where('parking_lot_id', $refundOrder->parking_lot_id)->where('paid_code', $refundOrder->paid_code)->where('refund_status', RefundOrder::STATUS_SUCCESS)->get();

            if ($hadRefundedOrders->count()) {
                if ($refundOrder->refund_amount <= $hadRefundedOrders->sum('refund_amount')) {
                    throw new \Exception('订单已退款');
                }
            }

            if ($refundOrder->payment_channel_id) {
                if (!$paymentChannel = $refundOrder->paymentChannel) {
                    throw new \Exception('关联的支付通道不存在或已被移除');
                }

                switch ($paymentChannel->category) {
                    case PaymentChannel::CATEGORY_CHINAUMS:
                        $refundResponse = (new ChinaUms($paymentChannel))->toRefund($refundOrder);
                        break;
                    case PaymentChannel::CATEGORY_UNIONPAY_APP:
                    case PaymentChannel::CATEGORY_UNIONPAY_ALIPAY:
                    case PaymentChannel::CATEGORY_UNIONPAY_WECHATPAY:
                    case PaymentChannel::CATEGORY_UNIONPAY_WECHATPAY_MINI:
                        $refundResponse = (new UnionPay($paymentChannel))->toRefund($refundOrder);
                        break;
                    case PaymentChannel::CATEGORY_FUIOUPAY:
                        $refundResponse = (new FuiouPay($paymentChannel))->toRefund($refundOrder);
                        break;
                    case PaymentChannel::CATEGORY_FUIOUPAY_AGGREGATE:
                        $refundResponse = (new FuiouAggregatePay($paymentChannel))->toRefund($refundOrder);
                        break;
                    case PaymentChannel::CATEGORY_EBANKPAY:
                        $refundResponse = (new EbankPay($paymentChannel))->toRefund($refundOrder);
                        break;
                    default:
                        throw new \Exception('未启用的支付通道类型');
                }

                if ((\Arr::get($refundResponse, 'result_code') === 'SUCCESS') && (\Arr::get($refundResponse, 'return_code') === 'SUCCESS')) {
                    $refundOrder->refund_status = RefundOrder::STATUS_SUCCESS;
                    $refundSuccess = true;
                } else {
                    $refundOrder->error = strval(\Arr::get($refundResponse, 'return_msg'));
                    $refundOrder->refund_status = RefundOrder::STATUS_FAILED;
                }
            } else {
                $refundOrder->refund_status = RefundOrder::STATUS_SUCCESS;
                $refundSuccess = true;
            }

            $refundOrder->save();
        } catch (\Throwable $exception) {
            $err = $exception->getMessage();
            app(LoggerInterface::class)->error($exception->getMessage(), ['exception' => $err, 'trigger' => '订单退款脚本']);
        } finally {
            if ($refundSuccess) {
                if ($relatedOrder = $refundOrder->related) {
                    $refundAmount = $relatedOrder->refund_amount + $refundOrder->refund_amount;
                    $relatedOrder->update(['refund_amount' => $refundAmount]);
                }
            }
            else {
                $refundOrder->update(['refund_status' => RefundOrder::STATUS_FAILED, 'error' => $err]);
            }
        }
    }
}
